{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data loader testing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/yyjau/Documents/deepSfm_test\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "module_path = os.path.abspath(os.path.join('..'))\n",
    "if module_path not in sys.path:\n",
    "    sys.path.append(module_path)\n",
    "os.chdir('../')\n",
    "print(os.getcwd())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>.container { width:100% !important; }</style>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import logging\n",
    "\n",
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "from IPython.core.display import display, HTML\n",
    "display(HTML(\"<style>.container { width:100% !important; }</style>\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def loadConfig(filename):\n",
    "    import yaml\n",
    "    with open(filename, 'r') as f:\n",
    "        config = yaml.load(f)\n",
    "    return config\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "env: TMPDIR=tmp/\n",
      "config:  {'data': {'name': 'patches_dataset', 'dataset': 'hpatches', 'alteration': 'all', 'preprocessing': {'resize': [240, 320]}}, 'front_end_model': 'Val_model_heatmap', 'model': {'name': 'SuperPointNet_gauss2', 'params': {}, 'detection_threshold': 0.015, 'batch_size': 1, 'eval_batch_size': 1, 'learning_rate': 0.001, 'nms': 4, 'top_k': 1000, 'nn_thresh': 1.0, 'homography_adaptation': {'num': 0}, 'subpixel': {'enable': True, 'patch_size': 5}, 'rand_noise': {'enable': False, 'sigma': 0.2}, 'pretrained': 'logs/superpoint_coco/checkpoints/superPointNet_180_checkpoint.pth.tar'}, 'eval_iter': 1000}\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/yyjau/anaconda3/envs/py36-sp/lib/python3.6/site-packages/ipykernel_launcher.py:4: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.\n",
      "  after removing the cwd from sys.path.\n"
     ]
    }
   ],
   "source": [
    "# load config\n",
    "logging.basicConfig(format='[%(asctime)s %(levelname)s] %(message)s',\n",
    "                        datefmt='%m/%d/%Y %H:%M:%S', level=logging.INFO)\n",
    "\n",
    "%env TMPDIR=tmp/\n",
    "# filename = 'configs/magicpoint_kitti_train.yaml'\n",
    "# filename = 'configs/superpoint_coco_train_heatmap.yaml'\n",
    "# filename = 'configs/superpoint_kitti_train_heatmap.yaml'\n",
    "# filename = 'configs/magicpoint_coco_export.yaml'\n",
    "# filename = 'configs/magicpoint_shapes.yaml'\n",
    "# filename = 'configs/magicpoint_shapes_pair.yaml'\n",
    "filename = 'configs/magicpoint_repeatability_heatmap.yaml'\n",
    "config = loadConfig(filename)\n",
    "print(\"config: \", config)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "580\n"
     ]
    }
   ],
   "source": [
    "## test set\n",
    "from utils.loader import dataLoader_test as dataLoader\n",
    "task = config['data']['dataset']\n",
    "data = dataLoader(config, dataset=task)\n",
    "test_set, test_loader = data['test_set'], data['test_loader']\n",
    "print(f\"{len(test_set)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "task:  hpatches\n"
     ]
    },
    {
     "ename": "ModuleNotFoundError",
     "evalue": "No module named 'datasets.hpatches'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-6-510d3a16dd42>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0mtask\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mconfig\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'data'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'dataset'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"task: \"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdataLoader\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconfig\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdataset\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtask\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwarp_input\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m \u001b[0;31m# data\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/Documents/deepSfm_test/utils/loader.py\u001b[0m in \u001b[0;36mdataLoader\u001b[0;34m(config, dataset, warp_input, train, val)\u001b[0m\n\u001b[1;32m     85\u001b[0m         \u001b[0;32mfrom\u001b[0m \u001b[0mdatasets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSyntheticDataset_gaussian\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mSyntheticDataset\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mDataset\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     86\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 87\u001b[0;31m         \u001b[0mDataset\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_module\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'datasets'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdataset\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     88\u001b[0m         \u001b[0;31m# from datasets.coco import Coco as Dataset\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     89\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/Documents/deepSfm_test/utils/loader.py\u001b[0m in \u001b[0;36mget_module\u001b[0;34m(path, name)\u001b[0m\n\u001b[1;32m    183\u001b[0m         \u001b[0mmod\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mimportlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mimport_module\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    184\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 185\u001b[0;31m         \u001b[0mmod\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mimportlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mimport_module\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'{}.{}'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    186\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    187\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/envs/py36-sp/lib/python3.6/importlib/__init__.py\u001b[0m in \u001b[0;36mimport_module\u001b[0;34m(name, package)\u001b[0m\n\u001b[1;32m    124\u001b[0m                 \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    125\u001b[0m             \u001b[0mlevel\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 126\u001b[0;31m     \u001b[0;32mreturn\u001b[0m \u001b[0m_bootstrap\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_gcd_import\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mlevel\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpackage\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlevel\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    127\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    128\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/envs/py36-sp/lib/python3.6/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m_gcd_import\u001b[0;34m(name, package, level)\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/envs/py36-sp/lib/python3.6/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load\u001b[0;34m(name, import_)\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/envs/py36-sp/lib/python3.6/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load_unlocked\u001b[0;34m(name, import_)\u001b[0m\n",
      "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'datasets.hpatches'"
     ]
    }
   ],
   "source": [
    "from utils.loader import dataLoader\n",
    "task = config['data']['dataset']\n",
    "print(\"task: \", task)\n",
    "data = dataLoader(config, dataset=task, warp_input=True)\n",
    "\n",
    "# data\n",
    "train_loader, val_loader = data['train_loader'], data['val_loader']\n",
    "\n",
    "logging.info('== train split size %d in %d batches, val split size %d in %d batches'%\\\n",
    "        (len(train_loader)*config['model']['batch_size'], len(train_loader),\n",
    "         len(val_loader)*config['model']['batch_size'], len(val_loader)))\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "load training samples\n",
      "['image', 'valid_mask', 'labels_2D', 'labels_res', 'warped_labels_gaussian', 'warped_labels_bi', 'warped_img', 'warped_labels', 'warped_res', 'warped_valid_mask', 'homographies', 'inv_homographies', 'labels_2D_gaussian', 'name']\n"
     ]
    }
   ],
   "source": [
    "# val\n",
    "# for i, sample in enumerate(val_loader):\n",
    "#     if i > 1:\n",
    "#         print(list(sample))\n",
    "#         break\n",
    "# train\n",
    "print(\"load training samples\")\n",
    "for i, sample in enumerate(train_loader):\n",
    "    if i > 1:\n",
    "        print(list(sample))\n",
    "        break\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "metadata": {},
   "outputs": [],
   "source": [
    "from datasets.data_tools import np_to_tensor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## train set (not loader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/yoyee/Documents/deepSfm/datasets/SyntheticDataset_gaussian.py:410: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
      "  warped_img = torch.tensor(img, dtype=torch.float32)\n",
      "/home/yoyee/Documents/deepSfm/datasets/data_tools.py:9: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
      "  pnts = torch.tensor(pnts).long() ### check\n"
     ]
    }
   ],
   "source": [
    "train_set = data['train_set']\n",
    "sample = train_set[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'element' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-9-467168d0e3c2>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      3\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melement\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTensor\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m             \u001b[0msample\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msample\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munsqueeze\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdim\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0munsqueeze_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msample\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdim\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-9-467168d0e3c2>\u001b[0m in \u001b[0;36munsqueeze_dict\u001b[0;34m(sample, dim)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0munsqueeze_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msample\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdim\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m     \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msample\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m         \u001b[0;32mif\u001b[0m \u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melement\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTensor\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      4\u001b[0m             \u001b[0msample\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msample\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munsqueeze\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdim\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0munsqueeze_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msample\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdim\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'element' is not defined"
     ]
    }
   ],
   "source": [
    "def unsqueeze_dict(sample, dim=0):\n",
    "    for i in list(sample):\n",
    "        if type(element) is torch.Tensor:\n",
    "            sample[i] = sample[i].unsqueeze(dim)\n",
    "unsqueeze_dict(sample, dim=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## visualize data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "shape of  image   torch.Size([4, 1, 384, 1248])\n",
      "shape of  valid_mask   torch.Size([4, 1, 384, 1248])\n",
      "shape of  labels_2D   torch.Size([4, 1, 384, 1248])\n",
      "shape of  labels_res   torch.Size([4, 2, 384, 1248])\n",
      "shape of  warped_labels_gaussian   torch.Size([4, 1, 384, 1248])\n",
      "shape of  warped_labels_bi   torch.Size([4, 1, 384, 1248])\n",
      "shape of  warped_img   torch.Size([4, 1, 384, 1248])\n",
      "shape of  warped_labels   torch.Size([4, 1, 384, 1248])\n",
      "shape of  warped_res   torch.Size([4, 2, 384, 1248])\n",
      "shape of  warped_valid_mask   torch.Size([4, 1, 384, 1248])\n",
      "shape of  homographies   torch.Size([4, 3, 3])\n",
      "shape of  inv_homographies   torch.Size([4, 3, 3])\n",
      "shape of  labels_2D_gaussian   torch.Size([4, 1, 384, 1248])\n"
     ]
    }
   ],
   "source": [
    "# print shape\n",
    "entries = list(sample)\n",
    "for i in entries:\n",
    "    element = sample[i]\n",
    "#     print(type(element))\n",
    "    if type(element) is torch.Tensor:\n",
    "        print(\"shape of \", i, \" \", element.shape)\n",
    "img, labels_2D, mask_2D = sample['image'], sample['labels_2D'], sample['valid_mask']\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.float32"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sample['labels_2D_gaussian'].dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(384, 1248, 3)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def img_overlap(img_r, img_g, img_gray):  # img_b repeat\n",
    "    img = np.concatenate((img_gray, img_gray, img_gray), axis=0)\n",
    "    img[0, :, :] += img_r[0, :, :]\n",
    "    img[1, :, :] += img_g[0, :, :]\n",
    "    img[img > 1] = 1\n",
    "    img[img < 0] = 0\n",
    "    img = img.transpose([1,2,0])\n",
    "    return img\n",
    "def toNumpy(tensor):\n",
    "    return tensor.detach().cpu().numpy()\n",
    "\n",
    "result_overlap = img_overlap(toNumpy(1 - mask_2D[0,:,:,:]), toNumpy(labels_2D[0, :, :, :]), toNumpy(img[0, :, :, :]))\n",
    "print(result_overlap.shape)\n",
    "\n",
    "plt.imshow(result_overlap)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test gaussian"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gaussian:  [[0. 0. 0. ... 0. 0. 0.]\n",
      " [0. 0. 0. ... 0. 0. 0.]\n",
      " [0. 0. 0. ... 0. 0. 0.]\n",
      " ...\n",
      " [0. 0. 0. ... 0. 0. 0.]\n",
      " [0. 0. 0. ... 0. 0. 0.]\n",
      " [0. 0. 0. ... 0. 0. 0.]]\n",
      "kernel size:  0.2\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# gauss_map = sample['warped_labels_gaussian']\n",
    "# gauss_map = sample['warped_labels_gaussian']\n",
    "# gauss_map = sample['warped_labels']\n",
    "gauss_map = sample['labels_2D_gaussian']\n",
    "\n",
    "    \n",
    "plt.imshow(toNumpy(gauss_map[0,0,:,:]))\n",
    "print(\"gaussian: \", toNumpy(gauss_map[0,0,:,:]))\n",
    "print(\"kernel size: \", config['data']['gaussian_label']['params']['GaussianBlur']['sigma'])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# gauss_map = sample['labels_2D'] # - sample['warped_labels_bi']\n",
    "maps = ['labels_2D', 'labels_2D_gaussian', 'warped_labels', 'warped_labels_gaussian']\n",
    "\n",
    "for m in maps:\n",
    "    gauss_map = sample[m]\n",
    "    plt.imshow(toNumpy(gauss_map[0,0,:,:]))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gaussian:  0.28627452\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# gauss_map = sample['warped_labels_gaussian'] - sample['warped_labels']\n",
    "gauss_map = sample['labels_2D_gaussian'] - sample['labels_2D']\n",
    "# gauss_map = sample['warped_labels']\n",
    "\n",
    "plt.imshow(toNumpy(gauss_map[0,0,:,:]))\n",
    "print(\"gaussian: \", toNumpy(gauss_map[0,0,:,:]).max())\n",
    "# print(\"kernel size: \", config['data']['gaussian_label']['sigma'])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gaussian:  2.0\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from utils.utils import inv_warp_image_batch\n",
    "labels_unwarp = inv_warp_image_batch(sample['warped_labels'], sample['homographies'], mode = 'nearest')\n",
    "# labels_unwarp = inv_warp_image_batch(sample['warped_labels_bi'], sample['homographies'], mode = 'nearest')\n",
    "# gauss_map = labels_unwarp - sample['labels_2D']\n",
    "# gauss_map = sample['labels_2D'] - labels_unwarp\n",
    "gauss_map = labels_unwarp\n",
    "# gauss_map = sample['warped_labels']\n",
    "\n",
    "plt.imshow(toNumpy(gauss_map[0,0,:,:]))\n",
    "print(\"gaussian: \", toNumpy(gauss_map[0,0,:,:]).sum())\n",
    "# print(\"kernel size: \", config['data']['gaussian_label']['sigma'])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gaussian:  -1.0\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "labels_ununwarp = inv_warp_image_batch(labels_unwarp, sample['inv_homographies'], mode = 'nearest')\n",
    "# labels_unwarp = inv_warp_image_batch(sample['warped_labels_bi'], sample['homographies'], mode = 'nearest')\n",
    "# gauss_map = labels_unwarp - sample['labels_2D']\n",
    "# gauss_map = sample['labels_2D'] - labels_unwarp\n",
    "gauss_map = labels_ununwarp - sample['warped_labels']\n",
    "# gauss_map = sample['warped_labels']\n",
    "\n",
    "plt.imshow(toNumpy(gauss_map[0,0,:,:]))\n",
    "print(\"gaussian: \", toNumpy(gauss_map[0,0,:,:]).sum())\n",
    "# print(\"kernel size: \", config['data']['gaussian_label']['sigma'])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## check gt patches prediction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "device='cuda:0'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/yoyee/.local/lib/python3.6/site-packages/ipykernel_launcher.py:3: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
      "  This is separate from the ipykernel package so we can avoid doing imports until\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "heatmap:  torch.float32\n",
      "heatmap:  tensor(1.)\n",
      "rois:  torch.int64\n",
      "patches:  torch.Size([1744, 1, 5, 5])\n"
     ]
    }
   ],
   "source": [
    "# uses labels_2D, heatmap\n",
    "# heatmap = gauss_map\n",
    "to_floatTensor = lambda x: torch.tensor(x).type(torch.FloatTensor)\n",
    "\n",
    "# for synthetic data\n",
    "def get_data(mode='coco'):\n",
    "    global labels_2D, heatmap\n",
    "    if mode == 'coco':\n",
    "        labels_2D = to_floatTensor(sample['warped_labels'])\n",
    "        heatmap = to_floatTensor(sample['warped_labels_gaussian'])        \n",
    "#         heatmap = to_floatTensor(sample['warped_labels_bi'])        \n",
    "    else:\n",
    "        labels_2D = to_floatTensor(sample['labels_2D'])\n",
    "        heatmap = to_floatTensor(sample['labels_2D_gaussian'])\n",
    "    \n",
    "        \n",
    "get_data(mode='coco')\n",
    "## crop patches from labels map\n",
    "from utils.losses import pts_to_bbox\n",
    "from utils.losses import _roi_pool\n",
    "\n",
    "patch_size=5\n",
    "points = labels_2D[...].nonzero()\n",
    "rois = pts_to_bbox(points[:,2:], patch_size=patch_size)\n",
    "rois = torch.cat((points[:,:1], rois), dim=1)\n",
    "print(\"heatmap: \", heatmap.dtype)\n",
    "print(\"heatmap: \", heatmap.max())\n",
    "print(\"rois: \", rois.dtype)\n",
    "patches = _roi_pool(heatmap.to(device), rois.to(device), patch_size=patch_size)\n",
    "print(\"patches: \", patches.shape)\n",
    "## softargmax"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches:  torch.Size([1744, 1, 5, 5])\n"
     ]
    }
   ],
   "source": [
    "## norm the patches\n",
    "import torch.nn as nn\n",
    "def norm_patches(patches):\n",
    "    patches = patches.view(-1, 1, patch_size*patch_size)\n",
    "    d = torch.sum(patches, dim=-1).unsqueeze(-1) + 1e-6\n",
    "    patches = patches/d\n",
    "    patches = patches.view(-1, 1, patch_size, patch_size)\n",
    "    print(\"patches: \", patches.shape)\n",
    "    return patches\n",
    "\n",
    "patches = norm_patches(patches)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.50592834\n",
      "patches[img_id,0,:,:] sum:  0.9999989\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.52173865\n",
      "patches[img_id,0,:,:] sum:  0.999999\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.59683734\n",
      "patches[img_id,0,:,:] sum:  0.9999989\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPgAAAD8CAYAAABaQGkdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAACOBJREFUeJzt3U+IXYUdxfFzOk5mjBZcNAuTCY0LEYKlSRlSIaumSOMfdJuAroRZtEIEQXTptgvJxs2gwYJBEXQhwSJpjYjURpMYxSRKg1hMkI5FRFNoYuLpYt4itZm8O3n3zp336/cDA/NmHncOYb5z33sz3DiJANT0o74HAOgOgQOFEThQGIEDhRE4UBiBA4UROFAYgQOFEThQ2HVdHHSNpzKtG7o4NABJ/9a/dCHnPex+nQQ+rRv0S/+6i0MDkHQ4f250Px6iA4UROFAYgQOFEThQGIEDhRE4UBiBA4UROFAYgQOFEThQGIEDhRE4UBiBA4UROFAYgQOFEThQWKPAbe+0/Ynt07Yf73oUgHYMDdz2hKSnJd0labOk3bY3dz0MwOianMG3STqd5NMkFyS9KOn+bmcBaEOTwDdI+vyy22cGHwOwyrV20UXbc5LmJGlaa9s6LIARNDmDn5W08bLbM4OP/Zck80lmk8xOaqqtfQBG0CTw9yTdavsW22sk7ZL0arezALRh6EP0JBdtPyzpdUkTkvYlOdH5MgAja/QcPMlrkl7reAuAlvGXbEBhBA4URuBAYQQOFEbgQGEEDhRG4EBhBA4URuBAYQQOFEbgQGEEDhRG4EBhBA4URuBAYQQOFEbgQGGtXVUVK+PSr37R94RlmfrbP/qe0NjFM/9zLdGxxxkcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwobGjgtvfZXrD90UoMAtCeJmfw5yTt7HgHgA4MDTzJW5K+WoEtAFrGc3CgsNauqmp7TtKcJE1rbVuHBTCC1s7gSeaTzCaZndRUW4cFMAIeogOFNfk12QuS3pF0m+0zth/qfhaANgx9Dp5k90oMAdA+HqIDhRE4UBiBA4UROFAYgQOFEThQGIEDhRE4UBiBA4UROFAYgQOFEThQGIEDhRE4UBiBA4UROFBYaxddxMr40/59fU9Ylp/t/W3fExpb//uzfU9oHWdwoDACBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKAwAgcKI3CgsKGB295o+5Dtk7ZP2N6zEsMAjK7JJZsuSno0yTHbP5Z01PbBJCc73gZgREPP4Em+SHJs8P63kk5J2tD1MACjW9ZzcNubJG2VdLiLMQDa1fiqqrZvlPSypEeSfHOFz89JmpOkaa1tbSCAa9foDG57Uotx70/yypXuk2Q+yWyS2UlNtbkRwDVq8iq6JT0r6VSSp7qfBKAtTc7g2yU9KGmH7eODt7s73gWgBUOfgyd5W5JXYAuAlvGXbEBhBA4URuBAYQQOFEbgQGEEDhRG4EBhBA4URuBAYQQOFEbgQGEEDhRG4EBhBA4URuBAYQQOFEbgQGGNr6qK1eE367f0PWFZ1usvfU/4v8YZHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKGxo4Lanbb9r+wPbJ2w/uRLDAIyuySWbzkvakeSc7UlJb9v+Y5K/drwNwIiGBp4kks4Nbk4O3tLlKADtaPQc3PaE7eOSFiQdTHK421kA2tAo8CSXkmyRNCNpm+3bf3gf23O2j9g+8p3Ot70TwDVY1qvoSb6WdEjSzit8bj7JbJLZSU21tQ/ACJq8ir7O9k2D96+XdKekj7seBmB0TV5Fv1nSH2xPaPEHwktJDnQ7C0AbmryK/qGkrSuwBUDL+Es2oDACBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKAwAgcKaxy47Qnb79s+0OUgAO1Zzhl8j6RTXQ0B0L5GgduekXSPpGe6nQOgTU3P4HslPSbp+w63AGjZ0MBt3ytpIcnRIfebs33E9pHvdL61gQCuXZMz+HZJ99n+TNKLknbYfv6Hd0oyn2Q2yeykplqeCeBaDA08yRNJZpJskrRL0htJHuh8GYCR8XtwoLDrlnPnJG9KerOTJQBaxxkcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwozEnaP6j9paS/t3zYn0j6Z8vH7NI47R2nrdJ47e1q60+TrBt2p04C74LtI0lm+97R1DjtHaet0njt7XsrD9GBwggcKGycAp/ve8AyjdPecdoqjdfeXreOzXNwAMs3TmdwAMs0FoHb3mn7E9unbT/e956rsb3P9oLtj/reMoztjbYP2T5p+4TtPX1vWortadvv2v5gsPXJvjc1YXvC9vu2D/Tx9Vd94LYnJD0t6S5JmyXttr2531VX9ZyknX2PaOiipEeTbJZ0h6TfreJ/2/OSdiT5uaQtknbavqPnTU3skXSqry++6gOXtE3S6SSfJrmgxf/h9P6eNy0pyVuSvup7RxNJvkhybPD+t1r8RtzQ76ory6Jzg5uTg7dV/QKS7RlJ90h6pq8N4xD4BkmfX3b7jFbpN+E4s71J0lZJh/tdsrTBw93jkhYkHUyyarcO7JX0mKTv+xowDoGjY7ZvlPSypEeSfNP3nqUkuZRki6QZSdts3973pqXYvlfSQpKjfe4Yh8DPStp42e2ZwcfQAtuTWox7f5JX+t7TRJKvJR3S6n6tY7uk+2x/psWnlTtsP7/SI8Yh8Pck3Wr7FttrJO2S9GrPm0qwbUnPSjqV5Km+91yN7XW2bxq8f72kOyV93O+qpSV5IslMkk1a/J59I8kDK71j1Qee5KKkhyW9rsUXgV5KcqLfVUuz/YKkdyTdZvuM7Yf63nQV2yU9qMWzy/HB2919j1rCzZIO2f5Qiz/0Dybp5VdP44S/ZAMKW/VncADXjsCBwggcKIzAgcIIHCiMwIHCCBwojMCBwv4DxjTQL8McfrkAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.6205528\n",
      "patches[img_id,0,:,:] sum:  0.99999905\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.9169951\n",
      "patches[img_id,0,:,:] sum:  0.9999989\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.59126925\n",
      "patches[img_id,0,:,:] sum:  0.999999\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.5118105\n",
      "patches[img_id,0,:,:] sum:  0.9999989\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.71428496\n",
      "patches[img_id,0,:,:] sum:  0.999999\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPgAAAD8CAYAAABaQGkdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAACN1JREFUeJzt3c+L3PUdx/HXK+smm2jBQ1Ow2dB4ECEITWCJQm4pYvyBXhPQk7CHVoggiPbmPyAetIdFgwVFEfQgwSKhRkRqo/mlmEQhiMWIsC0imkATY1497BxSyWa+u/P97nfn7fMBCzub4ZsXss98ZmaX0UkEoKY1fQ8A0B0CBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKCw67q46Fqvy5Su7+LSACT9V+d1MRc87H6dBD6l63W7/9DFpQFIOpy/N7ofD9GBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCisUeC2d9v+3PYZ2090PQpAO4YGbntC0nOS7pa0VdJe21u7HgZgdE1O8B2SziT5IslFSa9KeqDbWQDa0CTwTZK+uuL22cHXAKxyrb3pou1ZSbOSNKUNbV0WwAianOBfS9p8xe3pwdf+T5K5JDNJZia1rq19AEbQJPCPJN1i+2bbayXtkfRmt7MAtGHoQ/Qkl2w/IultSROS9ic52fkyACNr9Bw8yVuS3up4C4CW8ZtsQGEEDhRG4EBhBA4URuBAYQQOFEbgQGEEDhRG4EBhBA4URuBAYQQOFEbgQGEEDhRG4EBhBA4URuBAYa29q+rYWjPR94Ilmf/j7X1PWJLfPPuPvif8onGCA4UROFAYgQOFEThQGIEDhRE4UBiBA4UROFAYgQOFEThQGIEDhRE4UBiBA4UROFAYgQOFEThQGIEDhQ0N3PZ+2/O2P12JQQDa0+QEf1HS7o53AOjA0MCTvCfp2xXYAqBlPAcHCmvtXVVtz0qalaQpbWjrsgBG0NoJnmQuyUySmUmta+uyAEbAQ3SgsCY/JntF0geSbrV91vbD3c8C0Iahz8GT7F2JIQDax0N0oDACBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKAwAgcKI3CgMAIHCiNwoDACBwojcKAwAgcKa+1NF8fVmvVTfU9YkuN//kvfE5bkrme39T3hF40THCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKGxo4LY32z5k+5Ttk7b3rcQwAKNr8pZNlyQ9luSY7V9JOmr7YJJTHW8DMKKhJ3iSb5IcG3z+g6TTkjZ1PQzA6Jb0HNz2FknbJR3uYgyAdjV+V1XbN0h6XdKjSb6/yp/PSpqVpCltaG0ggOVrdILbntRC3C8neeNq90kyl2Qmycyk1rW5EcAyNXkV3ZJekHQ6ydPdTwLQliYn+E5JD0naZfvE4OOejncBaMHQ5+BJ3pfkFdgCoGX8JhtQGIEDhRE4UBiBA4UROFAYgQOFEThQGIEDhRE4UBiBA4UROFAYgQOFEThQGIEDhRE4UBiBA4UROFBY43dVrery+fN9T1iSu367re8JGCOc4EBhBA4URuBAYQQOFEbgQGEEDhRG4EBhBA4URuBAYQQOFEbgQGEEDhRG4EBhBA4URuBAYQQOFEbgQGFDA7c9ZftD2x/bPmn7qZUYBmB0Td6y6YKkXUnO2Z6U9L7tvyX5Z8fbAIxoaOBJIunc4Obk4CNdjgLQjkbPwW1P2D4haV7SwSSHu50FoA2NAk/yU5JtkqYl7bB928/vY3vW9hHbR37UhbZ3AliGJb2KnuQ7SYck7b7Kn80lmUkyM6l1be0DMIImr6JvtH3j4PP1ku6U9FnXwwCMrsmr6DdJ+qvtCS38g/BakgPdzgLQhiavon8iafsKbAHQMn6TDSiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwhoHbnvC9nHbB7ocBKA9SznB90k63dUQAO1rFLjtaUn3Snq+2zkA2tT0BH9G0uOSLne4BUDLhgZu+z5J80mODrnfrO0jto/8qAutDQSwfE1O8J2S7rf9paRXJe2y/dLP75RkLslMkplJrWt5JoDlGBp4kieTTCfZImmPpHeSPNj5MgAj4+fgQGHXLeXOSd6V9G4nSwC0jhMcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwojMCBwggcKIzAgcIIHCiMwIHCCBwozEnav6j9b0n/avmyv5b0n5av2aVx2jtOW6Xx2tvV1t8l2TjsTp0E3gXbR5LM9L2jqXHaO05bpfHa2/dWHqIDhRE4UNg4BT7X94AlGqe947RVGq+9vW4dm+fgAJZunE5wAEs0FoHb3m37c9tnbD/R955rsb3f9rztT/veMoztzbYP2T5l+6TtfX1vWoztKdsf2v54sPWpvjc1YXvC9nHbB/r4+1d94LYnJD0n6W5JWyXttb2131XX9KKk3X2PaOiSpMeSbJV0h6Q/reL/thck7Urye0nbJO22fUfPm5rYJ+l0X3/5qg9c0g5JZ5J8keSiFv4Ppw/0vGlRSd6T9G3fO5pI8k2SY4PPf9DCN+KmflddXRacG9ycHHys6heQbE9LulfS831tGIfAN0n66orbZ7VKvwnHme0tkrZLOtzvksUNHu6ekDQv6WCSVbt14BlJj0u63NeAcQgcHbN9g6TXJT2a5Pu+9ywmyU9JtkmalrTD9m19b1qM7fskzSc52ueOcQj8a0mbr7g9PfgaWmB7Ugtxv5zkjb73NJHkO0mHtLpf69gp6X7bX2rhaeUu2y+t9IhxCPwjSbfYvtn2Wkl7JL3Z86YSbFvSC5JOJ3m67z3XYnuj7RsHn6+XdKekz/pdtbgkTyaZTrJFC9+z7yR5cKV3rPrAk1yS9Iikt7XwItBrSU72u2pxtl+R9IGkW22ftf1w35uuYaekh7RwupwYfNzT96hF3CTpkO1PtPCP/sEkvfzoaZzwm2xAYav+BAewfAQOFEbgQGEEDhRG4EBhBA4URuBAYQQOFPY/zd/NhSEJBvcAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.6837938\n",
      "patches[img_id,0,:,:] sum:  0.999999\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "patches[img_id,0,:,:] max:  0.3517783\n",
      "patches[img_id,0,:,:] sum:  0.9999989\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# print patches\n",
    "def draw_center(patch, pos):\n",
    "    patch[...,pos,pos] = 1\n",
    "    return patch\n",
    "\n",
    "from utils.var_dim import toNumpy\n",
    "\n",
    "for i in range(10):\n",
    "    img_id = i\n",
    "#     print(\"res (x, y): \", points_res[i])\n",
    "#     plt.imshow(draw_center(toNumpy(patches[img_id,0,:,:]), 4))\n",
    "    p = toNumpy(patches[img_id,0,:,:])\n",
    "    plt.imshow(p)\n",
    "#     print(\"patches[img_id,0,:,:]: \", p)\n",
    "    print(\"patches[img_id,0,:,:] max: \", p.max())\n",
    "    print(\"patches[img_id,0,:,:] sum: \", p.sum())\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "labels_warped_res:  torch.Size([4, 2, 384, 1248])\n",
      "points_res:  torch.Size([1744, 2])\n"
     ]
    }
   ],
   "source": [
    "labels_warped_res = sample['warped_res']\n",
    "print(\"labels_warped_res: \", labels_warped_res.shape)\n",
    "# labels_warped_res = sample['warped_labels']\n",
    "# labels_warped_res = sample['labels_res']\n",
    "\n",
    "def ext_from_points(labels_res, points):\n",
    "    labels_res = labels_res.transpose(1,2).transpose(2,3).unsqueeze(1)\n",
    "    points_res = labels_res[points[:,0],points[:,1],points[:,2],points[:,3],:]  # tensor [N, 2]\n",
    "    return points_res\n",
    "    \n",
    "points_res = ext_from_points(labels_warped_res, points)\n",
    "print(\"points_res: \", points_res.shape)\n",
    "\n",
    "# points_res = label_to_points(labels_warped, points)\n",
    "# print(\"labels_warped: \", points_res.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "## log on patches\n",
    "def do_log(patches):\n",
    "    patches[patches==0] = patches[patches==0] + 1e-6\n",
    "    patches_log = torch.log(patches)\n",
    "    return patches_log\n",
    "\n",
    "# patches_log = do_log(patches)\n",
    "patches_log = do_log(patches)\n",
    "# patches_log = patches\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "points_res:  torch.Size([1744, 2])\n",
      "points_res:  tensor([[ 0.4430,  0.0929],\n",
      "        [ 0.0856, -0.4316],\n",
      "        [ 0.2845, -0.1680],\n",
      "        [ 0.2195, -0.2063],\n",
      "        [ 0.0432, -0.0491],\n",
      "        [ 0.2867, -0.1757],\n",
      "        [-0.1508,  0.3987],\n",
      "        [-0.0365, -0.2638],\n",
      "        [-0.0719,  0.2680],\n",
      "        [-0.3165, -0.4850]])\n",
      "dxdy:  torch.Size([1744, 2])\n",
      "dxdy:  tensor([[ 0.4427,  0.0909],\n",
      "        [ 0.0830, -0.4308],\n",
      "        [ 0.2846, -0.1660],\n",
      "        [ 0.2174, -0.2055],\n",
      "        [ 0.0395, -0.0435],\n",
      "        [ 0.2857, -0.1706],\n",
      "        [-0.1496,  0.3976],\n",
      "        [-0.0317, -0.2619],\n",
      "        [-0.0672,  0.2648],\n",
      "        [-0.3162, -0.4862]], device='cuda:0')\n",
      "errors:  tensor([0.0067, 0.0049])\n",
      "var:  tensor([0.0751, 0.0480])\n",
      "dxdy:  torch.Size([1744, 2])\n",
      "dxdy:  tensor([[ 0.2213,  0.0455],\n",
      "        [ 0.0415, -0.2154],\n",
      "        [ 0.1423, -0.0830],\n",
      "        [ 0.1087, -0.1028],\n",
      "        [ 0.0198, -0.0217],\n",
      "        [ 0.1429, -0.0853],\n",
      "        [-0.0748,  0.1988],\n",
      "        [-0.0159, -0.1309],\n",
      "        [-0.0336,  0.1324],\n",
      "        [-0.1581, -0.2431]], device='cuda:0')\n",
      "errors:  tensor([0.1249, 0.1283])\n",
      "var:  tensor([0.0845, 0.0774])\n"
     ]
    }
   ],
   "source": [
    "from utils.losses import soft_argmax_2d\n",
    "## point residual\n",
    "print(\"points_res: \", points_res.shape)\n",
    "print(\"points_res: \", points_res[:10])\n",
    "# print(\"points_res sum: \", points_res.sum())\n",
    "\n",
    "## no norm\n",
    "dxdy = soft_argmax_2d(patches_log, normalized_coordinates=False) # tensor [B, N, patch, patch]\n",
    "dxdy = dxdy.squeeze(1) # tensor [N, 2]\n",
    "dxdy = dxdy-patch_size//2\n",
    "print(\"dxdy: \", dxdy.shape)\n",
    "print(\"dxdy: \", dxdy[:10])\n",
    "num = 500\n",
    "print(\"errors: \", abs(dxdy[:num].cpu() - points_res[:num].cpu()).mean(dim=0))\n",
    "print(\"var: \", abs(dxdy[:num].cpu() - points_res[:num].cpu()).std(dim=0))\n",
    "# \n",
    "dxdy = soft_argmax_2d(patches_log, normalized_coordinates=True) # tensor [B, N, patch, patch]\n",
    "dxdy = dxdy.squeeze(1) # tensor [N, 2]\n",
    "print(\"dxdy: \", dxdy.shape)\n",
    "print(\"dxdy: \", dxdy[:10])\n",
    "print(\"errors: \", abs(dxdy[:num].cpu() - points_res[:num].cpu()).mean(dim=0))\n",
    "print(\"var: \", abs(dxdy[:num].cpu() - points_res[:num].cpu()).std(dim=0))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dxdy:  tensor([[[2.5000, 2.0000]]])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f2bb538bf98>"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "patch_test = torch.zeros((1,1,5,5))\n",
    "patch_test[0,0,2,2] = 1\n",
    "patch_test[0,0,2,3] = 1\n",
    "patches_log = do_log(patch_test)\n",
    "dxdy = soft_argmax_2d(patches_log, normalized_coordinates=False)\n",
    "print(\"dxdy: \", dxdy)\n",
    "\n",
    "plt.imshow(patch_test[0,0].numpy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'create_meshgrid' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-35-cdff15ed031c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     23\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0moutput\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mview\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch_size\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchannels\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# BxNx2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     24\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 25\u001b[0;31m \u001b[0mout_argmax\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtest_soft_argmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpatches\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-35-cdff15ed031c>\u001b[0m in \u001b[0;36mtest_soft_argmax\u001b[0;34m(input)\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     12\u001b[0m     \u001b[0;31m# create coordinates grid\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m     \u001b[0mpos_y\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpos_x\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcreate_meshgrid\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnormalized_coordinates\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     14\u001b[0m     \u001b[0mpos_x\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpos_x\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     15\u001b[0m     \u001b[0mpos_y\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpos_y\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'create_meshgrid' is not defined"
     ]
    }
   ],
   "source": [
    "def test_soft_argmax(input):\n",
    "    batch_size, channels, height, width = input.shape\n",
    "#     x: torch.Tensor = input.view(batch_size, channels, -1)\n",
    "\n",
    "    # compute softmax with max substraction trick\n",
    "#     exp_x = torch.exp(x - torch.max(x, dim=-1, keepdim=True)[0])\n",
    "    exp_x = input\n",
    "    eps = 1e-6\n",
    "    exp_x_sum = torch.tensor(\n",
    "        1.0) / (exp_x.sum(dim=-1, keepdim=True) + eps)\n",
    "\n",
    "    # create coordinates grid\n",
    "    pos_y, pos_x = create_meshgrid(input, self.normalized_coordinates)\n",
    "    pos_x = pos_x.reshape(-1)\n",
    "    pos_y = pos_y.reshape(-1)\n",
    "\n",
    "    # compute the expected coordinates\n",
    "    expected_y: torch.Tensor = torch.sum(\n",
    "        (pos_y * exp_x) * exp_x_sum, dim=-1, keepdim=True)\n",
    "    expected_x: torch.Tensor = torch.sum(\n",
    "        (pos_x * exp_x) * exp_x_sum, dim=-1, keepdim=True)\n",
    "    output: torch.Tensor = torch.cat([expected_x, expected_y], dim=-1)\n",
    "    return output.view(batch_size, channels, 2)  # BxNx2\n",
    "\n",
    "out_argmax = test_soft_argmax(patches)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## test labels 3D"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "labels_3D:  torch.Size([16, 64, 15, 20])\n",
      "labels_3D sum:  torch.Size([15, 20])\n",
      "labels_3D sum:  tensor([[0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.8863, 0.0824, 0.0000, 0.0000,\n",
      "         0.9843, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.9804, 0.0000, 0.0000, 0.0157, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.8824, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000, 0.7882, 0.0275, 0.0000, 0.0000, 0.9961, 0.0000,\n",
      "         0.0000, 0.0980, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.9882, 0.0000, 0.0000, 0.1608, 0.0039, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000, 0.0000, 0.9765, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.9922, 0.0000, 0.0000, 0.9725,\n",
      "         0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.9922, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0471, 0.0000, 0.0000, 0.9098, 0.0745, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.9804, 0.0000, 0.0000,\n",
      "         0.0000, 0.9412, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.7843, 0.2039, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.9843, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.9255,\n",
      "         0.0000, 0.0000, 0.8824, 0.0980, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.0667, 0.0000, 0.0000, 0.0000, 0.9843, 0.0000, 0.0000, 0.0000, 0.0549,\n",
      "         0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000],\n",
      "        [0.9176, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
      "         0.0000, 0.0000]])\n"
     ]
    }
   ],
   "source": [
    "from utils.d2s import DepthToSpace, SpaceToDepth\n",
    "\n",
    "labels_2D = sample['labels_2D_gaussian']\n",
    "space2depth = SpaceToDepth(8)\n",
    "labels_3D = space2depth(labels_2D)\n",
    "\n",
    "print(\"labels_3D: \", labels_3D.shape)\n",
    "labels_sum = labels_3D[2].sum(dim=0)\n",
    "print(\"labels_3D sum: \", labels_sum.shape)\n",
    "print(\"labels_3D sum: \", labels_sum)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## test on train_set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## test residual map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# syn\n",
    "# labels_warped_res = sample['labels_res']\n",
    "# warped_labels = sample['labels_2D']\n",
    "# warped_img = sample['image']\n",
    "\n",
    "# coco\n",
    "labels_warped_res = sample['warped_res']\n",
    "warped_labels = sample['warped_labels']\n",
    "warped_img = sample['warped_img']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "img_id = 0\n",
    "\n",
    "print(\"labels_warped_res: \", labels_warped_res.sum())\n",
    "print(\"labels_warped_res: \", labels_warped_res.shape)\n",
    "res_img = torch.norm(labels_warped_res, dim=1)\n",
    "plt.imshow(toNumpy(res_img[img_id,:,:]))\n",
    "plt.show()\n",
    "\n",
    "# warped_labels\n",
    "plt.imshow(toNumpy(warped_labels[img_id,0,:,:]))\n",
    "plt.show()\n",
    "\n",
    "\n",
    "# warped image\n",
    "plt.imshow(toNumpy(warped_img[img_id,0,:,:]))\n",
    "plt.show()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "def subpixel_loss(labels_2D, labels_res, pred_heatmap, batch_size, patch_size=7):\n",
    "    \"\"\"\n",
    "    \n",
    "    \"\"\"\n",
    "    # \n",
    "    def pts_to_bbox(points, patch_size):  \n",
    "        \"\"\"\n",
    "        input: \n",
    "            points: (y, x)\n",
    "        output:\n",
    "            bbox: (x1, y1, x2, y2)\n",
    "        \"\"\"\n",
    "\n",
    "        shift_l = patch_size / 2\n",
    "        shift_r = patch_size - shift_l\n",
    "#         bbox = torch.stack((points-shift_l, points+shift_r), dim=1)\n",
    "        pts_l = points-shift_l\n",
    "        pts_r = points+shift_r+1\n",
    "        bbox = torch.stack((pts_l[:,1], pts_l[:,0], pts_r[:,1], pts_r[:,0]), dim=1)\n",
    "        return bbox\n",
    "        pass\n",
    "    # roi pooling\n",
    "    def _roi_pool(pred_heatmap, rois):\n",
    "        from utils.roi_pool import RoIPool  # noqa: E402\n",
    "        m = RoIPool(patch_size, 1.0)\n",
    "        patches = m(pred_heatmap, rois.float())\n",
    "        return patches\n",
    "    \n",
    "    # soft argmax\n",
    "    def _soft_argmax(patches):\n",
    "        from models.SubpixelNet import SubpixelNet as subpixNet\n",
    "        dxdy = subpixNet.soft_argmax_2d(patches) # tensor [B, N, patch, patch]\n",
    "        dxdy = dxdy.squeeze(1) # tensor [N, 2]\n",
    "        return dxdy\n",
    "    \n",
    "    def print_var(points):\n",
    "        print(\"points: \", points.shape)\n",
    "        print(\"points: \", points)\n",
    "        pass\n",
    "   \n",
    "    points = labels_2D[...].nonzero()\n",
    "    labels_res = labels_res.transpose(1,2).transpose(2,3).unsqueeze(1)\n",
    "    rois = pts_to_bbox(points[:,2:], patch_size)\n",
    "    # filter out??\n",
    "    rois = torch.cat((points[:,:1], rois), dim=1)\n",
    "    points_res = labels_res[points[:,0],points[:,1],points[:,2],points[:,3],:]  # tensor [N, 2]\n",
    "#     print_var(rois)\n",
    "#     print_var(labels_res)\n",
    "#     print_var(points)\n",
    "#     print(\"points max: \", points.max(dim=0))\n",
    "#     print_var(labels_2D)\n",
    "#     print_var(points_res)\n",
    "    \n",
    "\n",
    "    patches = _roi_pool(pred_heatmap, rois)\n",
    "    # get argsoft max\n",
    "    dxdy = _soft_argmax(patches)\n",
    "\n",
    "    loss = (points_res - dxdy)\n",
    "#     loss = torch.norm(loss, p=2, dim=-1)\n",
    "#     loss = loss.sum()\n",
    "#     print(\"loss: \", loss)\n",
    "    return patches, points_res, dxdy, loss\n",
    "    pass\n",
    "\n",
    "patch_size = 8\n",
    "device='cuda:0'\n",
    "outs = subpixel_loss(warped_labels.to(device), labels_warped_res.to(device), warped_img.to(device), 8, patch_size=patch_size)\n",
    "patches, points_res, dxdy = outs[0], outs[1], outs[2]\n",
    "for i in range(10):\n",
    "    img_id = i\n",
    "    def draw_center(patch):\n",
    "        patch[...,3,3] = 1\n",
    "        return patch\n",
    "        \n",
    "    print(\"softmax dxdy (y, x): \", dxdy[i])\n",
    "    print(\"points_res (y, x): \", points_res[i])\n",
    "#     plt.imshow(toNumpy(patches[img_id,0,:,:]))\n",
    "    plt.imshow(toNumpy(draw_center(patches[img_id,0,:,:])))\n",
    "    plt.show()\n",
    "\n",
    "outs = subpixel_loss(warped_labels.to(device), labels_warped_res.to(device), res_img.unsqueeze(1).to(device), 8, patch_size=patch_size)\n",
    "patches, points_res = outs[0], outs[1]\n",
    "for i in range(10):\n",
    "    img_id = i\n",
    "    plt.imshow(toNumpy(patches[img_id,0,:,:]))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from utils.losses import subpixel_loss as loss_f\n",
    "loss = loss_f(warped_labels.to(device), labels_warped_res.to(device), warped_labels.to(device), patch_size=11)\n",
    "print(\"loss: \", loss)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "from utils.losses import subpixel_loss_no_argmax as loss_f\n",
    "loss = loss_f(warped_labels.to(device), labels_warped_res.to(device), warped_labels.to(device), patch_size=11)\n",
    "print(\"loss: \", loss)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_model(path, name):\n",
    "    mod = __import__('{}'.format(path), fromlist=[''])\n",
    "    return getattr(mod, name)\n",
    "get_model('utils.losses', 'subpixel_loss_no_argmax')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from models.SubpixelNet import SubpixelNet\n",
    "net = SubpixelNet(subpixel_channel=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test predicting flow on pixels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"labels_2D: \", labels_2D.shape)\n",
    "print(\"labels_2D sum: \", labels_2D.sum())\n",
    "print(\"warped_img: \", warped_img.shape)\n",
    "img_warp = warped_img"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# extract the patches from labels \n",
    "label_idx = labels_2D[...].nonzero()\n",
    "from utils.losses import extract_patches\n",
    "patches = extract_patches(label_idx.to(device), img_warp.to(device), patch_size=32) # tensor [N, patch_size, patch_size]\n",
    "# patches = extract_patches(label_idx.to(device), labels_2D.to(device), patch_size=15) # tensor [N, patch_size, patch_size]\n",
    "print(\"patches: \", patches.shape)\n",
    "\n",
    "def label_to_points(labels_res, points):\n",
    "    labels_res = labels_res.transpose(1,2).transpose(2,3).unsqueeze(1)\n",
    "    points_res = labels_res[points[:,0],points[:,1],points[:,2],points[:,3],:]  # tensor [N, 2]\n",
    "    return points_res\n",
    "    \n",
    "points_res = label_to_points(labels_warped_res, label_idx)\n",
    "print(\"points_res: \", points_res.shape)\n",
    "\n",
    "for i in range(10):\n",
    "    img_id = i\n",
    "    plt.imshow(toNumpy(patches[img_id,0,:,:]))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Testing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from utils.loader import get_module\n",
    "train_model_frontend = get_module('', 'Train_model_subpixel')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "'{}.{}'.format('path', 'name')\n",
    "import importlib\n",
    "name = 'Train_model_subpixel'\n",
    "mod = importlib.import_module(name)\n",
    "getattr(mod, name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualize warped images (for joint training)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# entries = ['image', 'labels_2D', 'valid_mask', 'overlay']\n",
    "# entries = ['warped_img', 'warped_labels', 'warped_valid_mask', 'overlay']\n",
    "entries = ['image', 'warped_img']\n",
    "cols = len(entries)\n",
    "scale = 5\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# show images\n",
    "images_num = config['model']['batch_size']\n",
    "col_row_ratio = 2\n",
    "iter_max = 2\n",
    "rows = images_num + 1\n",
    "\n",
    "task_folder = ['matching']\n",
    "print(\"load training samples\")\n",
    "for it, sample in enumerate(train_loader):\n",
    "    # break if max iteration\n",
    "    print(\"iter: \", it)\n",
    "    \n",
    "    if it > iter_max:\n",
    "        print(list(sample))\n",
    "        break\n",
    "    plt.figure(figsize=(cols*col_row_ratio*scale, rows*scale))    \n",
    "    count = 1   \n",
    "    for i in range(images_num):\n",
    "        for j in range(cols):\n",
    "    #         exp_path = Path(base_path, folder[j], prediction, task_folder[0])\n",
    "    #         path = exp_path / (str(i) + 'm.png')\n",
    "    #         image = load_as_float(path)\n",
    "#             print(entries[j])\n",
    "\n",
    "            if entries[j] == 'overlay':\n",
    "                img, labels_2D, mask_2D = sample[entries[0]], sample[entries[1]], sample[entries[2]]\n",
    "                image = img_overlap(toNumpy(1 - mask_2D[i,:,:,:]), \n",
    "                    toNumpy(labels_2D[i, :, :, :]), toNumpy(img[i, :, :, :]))\n",
    "            else:\n",
    "                image = sample[entries[j]][i,0,:,:]\n",
    "                image = image.numpy()\n",
    "#                 print(\"image: \", image.shape)\n",
    "#             print(\"count: \", count)\n",
    "#             print(\"rows: \", rows)\n",
    "#             print(\"cols: \", cols)\n",
    "            plt.subplot(rows, cols, count)\n",
    "            count += 1\n",
    "            \n",
    "            plt.axis('off')\n",
    "            plt.title(entries[j] + '/' + str(i))\n",
    "#             print(\"image: \", image)\n",
    "            plt.imshow(image, cmap='gray')\n",
    "            plt.tight_layout()\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "print(\"load validation samples\")\n",
    "for it, sample in enumerate(val_loader):\n",
    "    # break if max iteration\n",
    "    print(\"iter: \", it)\n",
    "    \n",
    "    if it > iter_max:\n",
    "        print(list(sample))\n",
    "        break\n",
    "    plt.figure(figsize=(cols*col_row_ratio*scale, rows*scale))    \n",
    "    count = 1   \n",
    "    for i in range(images_num):\n",
    "        for j in range(cols):\n",
    "    #         exp_path = Path(base_path, folder[j], prediction, task_folder[0])\n",
    "    #         path = exp_path / (str(i) + 'm.png')\n",
    "    #         image = load_as_float(path)\n",
    "#             print(entries[j])\n",
    "\n",
    "            if entries[j] == 'overlay':\n",
    "                img, labels_2D, mask_2D = sample[entries[0]], sample[entries[1]], sample[entries[2]]\n",
    "                image = img_overlap(toNumpy(1 - mask_2D[i,:,:,:]), \n",
    "                    toNumpy(labels_2D[i, :, :, :]), toNumpy(img[i, :, :, :]))\n",
    "            else:\n",
    "                image = sample[entries[j]][i,0,:,:]\n",
    "                image = image.numpy()\n",
    "#                 print(\"image: \", image.shape)\n",
    "#             print(\"count: \", count)\n",
    "#             print(\"rows: \", rows)\n",
    "#             print(\"cols: \", cols)\n",
    "            plt.subplot(rows, cols, count)\n",
    "            count += 1\n",
    "            \n",
    "            plt.axis('off')\n",
    "            plt.title(entries[j] + '/' + str(i))\n",
    "#             print(\"image: \", image)\n",
    "            plt.imshow(image, cmap='gray')\n",
    "            plt.tight_layout()\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualize images w/o homography augmentation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# entries = ['image', 'labels_2D', 'valid_mask', 'overlay']\n",
    "entries = ['warped_img', 'warped_labels', 'warped_valid_mask', 'overlay']\n",
    "cols = len(entries)\n",
    "scale = 10\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "# show images\n",
    "count = 1\n",
    "images_num = 2\n",
    "col_row_ratio = 3\n",
    "rows = images_num\n",
    "plt.figure(figsize=(cols*col_row_ratio*scale, rows*scale))\n",
    "\n",
    "task_folder = ['matching']\n",
    "for i in range(images_num):\n",
    "    for j in range(cols):\n",
    "#         exp_path = Path(base_path, folder[j], prediction, task_folder[0])\n",
    "#         path = exp_path / (str(i) + 'm.png')\n",
    "#         image = load_as_float(path)\n",
    "        print(entries[j])\n",
    "\n",
    "        if entries[j] == 'overlay':\n",
    "            img, labels_2D, mask_2D = sample[entries[0]], sample[entries[1]], sample[entries[2]]\n",
    "            image = img_overlap(toNumpy(1 - mask_2D[i,:,:,:]), \n",
    "                toNumpy(labels_2D[i, :, :, :]), toNumpy(img[i, :, :, :]))\n",
    "        else:\n",
    "            image = sample[entries[j]][i,0,:,:]\n",
    "            image = image.numpy()\n",
    "        plt.subplot(rows, cols, count)\n",
    "        count += 1\n",
    "        plt.axis('off')\n",
    "        plt.title(entries[j] + '/' + str(i))\n",
    "        plt.imshow(image, cmap='gray')\n",
    "        plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mask_2D.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Homography Adaptation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# data loading\n",
    "from utils.loader import dataLoader_test as dataLoader\n",
    "# data = dataLoader(config, dataset='hpatches')\n",
    "export_task = config['data']['export_folder']\n",
    "\n",
    "data = dataLoader(config, dataset=task, export_task=export_task)\n",
    "test_set, test_loader = data['test_set'], data['test_loader']\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# @torch.no_grad()\n",
    "from tqdm import tqdm\n",
    "from utils.utils import img_overlap, toNumpy\n",
    "\n",
    "device = 'cpu'\n",
    "\n",
    "count = 1\n",
    "images_num = 2\n",
    "col_row_ratio = 1\n",
    "rows = 10\n",
    "cols = 10\n",
    "scale = 5\n",
    "iter_max = 0\n",
    "plt.figure(figsize=(cols*col_row_ratio*scale, rows*scale))\n",
    "plot_inputs = True\n",
    "\n",
    "for i, sample in tqdm(enumerate(test_loader)):\n",
    "    img, mask_2D = sample['image'], sample['valid_mask']\n",
    "    img = img.transpose(0,1)\n",
    "    img_2D = img.numpy().squeeze()\n",
    "    mask_2D = mask_2D.transpose(0,1)\n",
    "    mask_2D_numpy = mask_2D.numpy()\n",
    "\n",
    "    inv_homographies, homographies = sample['homographies'], sample['inv_homographies']\n",
    "    img, mask_2D, homographies, inv_homographies = img.to(device), mask_2D.to(device), \\\n",
    "                                                   homographies.to(device), inv_homographies.to(device)\n",
    "    \n",
    "    def plotImg(rows, cols, count, image, name=''):\n",
    "        plt.subplot(rows, cols, count)\n",
    "        count += 1\n",
    "\n",
    "        plt.axis('off')\n",
    "        plt.title(name + '/' + str(i))\n",
    "        print(\"image: \", image.shape)\n",
    "        plt.imshow(image)\n",
    "        plt.tight_layout()\n",
    "    print(\"img_2D: \", img_2D.shape)\n",
    "    print(\"mask_2D: \", mask_2D.shape)\n",
    "    \n",
    "    if plot_inputs:\n",
    "        for j in range(img.shape[0]):\n",
    "            image = img_overlap((1 - mask_2D_numpy[j,:,:]), \n",
    "                    np.zeros_like(img_2D[j,:,:]), img_2D[j,:,:])\n",
    "            plotImg(rows, cols, count, image.transpose([1,2,0]),'warped-')\n",
    "            count += 1\n",
    "    def homography_adaptation(heatmap, inv_homographies, mask_2D, config):\n",
    "        from utils.utils import inv_warp_image_batch\n",
    "\n",
    "        ## multiply heatmap with mask_2D\n",
    "        heatmap = heatmap*mask_2D\n",
    "\n",
    "        heatmap = inv_warp_image_batch(heatmap, inv_homographies[0,:,:,:], device=device, mode='bilinear')\n",
    "\n",
    "        ##### check\n",
    "        mask_2D = inv_warp_image_batch(mask_2D, inv_homographies[0,:,:,:], device=device, mode='bilinear')\n",
    "        heatmap = torch.sum(heatmap, dim=0)\n",
    "        mask_2D = torch.sum(mask_2D, dim=0)\n",
    "        return heatmap/mask_2D\n",
    "    pass\n",
    "    image = homography_adaptation(img, inv_homographies, mask_2D, config)\n",
    "    print(\"image: \", image.shape)\n",
    "#     plotImg(rows, cols, count, toNumpy(image), name='')\n",
    "    \n",
    "    if i>iter_max: break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# plotImg(rows, cols, count, toNumpy(image).squeeze(), name='')\n",
    "image_np = toNumpy(image).squeeze()\n",
    "plt.imshow(image_np)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m = mask_2D_numpy[j,:,:]\n",
    "image = img_overlap((1 - mask_2D_numpy[j,:,:]), \n",
    "        np.zeros_like(img_2D[j,:,:]), img_2D[j,:,:])\n",
    "print(\"m: \", m.shape)\n",
    "print(\"image: \", image.shape)\n",
    "plt.imshow(image.transpose([1,2,0]))\n",
    "plt.show()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# show homography adaptation images\n",
    "# show images\n",
    "images_num = config['data']['homography_adaptation']['num']\n",
    "col_row_ratio = 2\n",
    "iter_max = 20\n",
    "rows = images_num + 1\n",
    "\n",
    "task_folder = ['matching']\n",
    "print(\"load training samples\")\n",
    "for it, sample in enumerate(train_loader):\n",
    "    # break if max iteration\n",
    "    print(\"iter: \", it)\n",
    "    \n",
    "    if it > iter_max:\n",
    "        print(list(sample))\n",
    "        break\n",
    "    plt.figure(figsize=(cols*col_row_ratio*scale, rows*scale))    \n",
    "    count = 1   \n",
    "    for i in range(images_num):\n",
    "        for j in range(cols):\n",
    "    #         exp_path = Path(base_path, folder[j], prediction, task_folder[0])\n",
    "    #         path = exp_path / (str(i) + 'm.png')\n",
    "    #         image = load_as_float(path)\n",
    "#             print(entries[j])\n",
    "\n",
    "            if entries[j] == 'overlay':\n",
    "                img, labels_2D, mask_2D = sample[entries[0]], sample[entries[1]], sample[entries[2]]\n",
    "                image = img_overlap(toNumpy(1 - mask_2D[i,:,:,:]), \n",
    "                    toNumpy(labels_2D[i, :, :, :]), toNumpy(img[i, :, :, :]))\n",
    "            else:\n",
    "                image = sample[entries[j]][i,0,:,:]\n",
    "                image = image.numpy()\n",
    "#                 print(\"image: \", image.shape)\n",
    "#             print(\"count: \", count)\n",
    "#             print(\"rows: \", rows)\n",
    "#             print(\"cols: \", cols)\n",
    "            plt.subplot(rows, cols, count)\n",
    "            count += 1\n",
    "            \n",
    "            plt.axis('off')\n",
    "            plt.title(entries[j] + '/' + str(i))\n",
    "#             print(\"image: \", image)\n",
    "            plt.imshow(image, cmap='gray')\n",
    "            plt.tight_layout()\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    path = config['pretrained']\n",
    "    print('==> Loading pre-trained network.')\n",
    "    print('path: ', path)\n",
    "    # This class runs the SuperPoint network and processes its outputs.\n",
    "\n",
    "    fe = SuperPointFrontend_torch(weights_path=path,\n",
    "                            nms_dist=nms_dist,\n",
    "                            conf_thresh=conf_thresh,\n",
    "                            nn_thresh=nn_thresh,\n",
    "                            cuda=False,\n",
    "                            device=device)\n",
    "    print('==> Successfully loaded pre-trained network.')\n",
    "\n",
    "    fe.net_parallel()\n",
    "    print(path)\n",
    "    # save to files\n",
    "    save_file = save_output / \"export.txt\"\n",
    "    with open(save_file, \"a\") as myfile:\n",
    "        myfile.write(\"load model: \" + path + '\\n')\n",
    "except Exception:\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py36-sp",
   "language": "python",
   "name": "py36-sp"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
